﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Reflection;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Xms.Abp.Data;

namespace Xms.Abp.Storage;

public class StorageDesignTimeFactory<TStorage>
    : IDesignTimeDbContextFactory<TStorage>
    where TStorage : XmsStorage<TStorage>
{
    public TStorage CreateDbContext(string[] args)
    {
        var type = typeof(TStorage);
        Console.WriteLine($"Creating Storage [{type.Name}]......");
        var configuration = BuildConfiguration();

        var dbType = configuration["DbContextOptions:DefaultDbType"]?.ToLower() ?? "mysql";

        var connectionStringKey = type.GetCustomAttribute<ConnectionStringNameAttribute>()?.Name
            ?? type.GetCustomAttribute<DynamicConnStringNameAttribute>()?.Name
            ?? "Default";

        var connectionString = configuration.GetConnectionString(connectionStringKey) ?? configuration.GetConnectionString("Default");

        Console.WriteLine(type.Name + "'s connectiong string is:" + connectionString);

        var builder = new DbContextOptionsBuilder<TStorage>();
        var assemblyName = GetType().Assembly.FullName;
        builder = dbType switch
        {
            "postgresql" => builder.UseNpgsql(connectionString, b => b.MigrationsAssembly(assemblyName)),
            "sqlserver" => builder.UseSqlServer(connectionString, b => b.MigrationsAssembly(assemblyName)),
            //"oracle" => (DbContextOptionsBuilder<TStorage>)builder.UseOracle(connectionString, b => b.MigrationsAssembly(assemblyName)),
            "sqlite" => builder.UseSqlite(connectionString, b => b.MigrationsAssembly(assemblyName)),
            "mysql" => builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), b => b.MigrationsAssembly(assemblyName)),
            _ => builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), b => b.MigrationsAssembly(assemblyName)),
        };

        var services = new ServiceCollection();
        services.Configure<XmsStorageConfigurationOptions<TStorage>>(options => { });
        ConfigureServices(services);
        var serviceProvider = services.BuildServiceProvider();

        var storage = (TStorage)Activator.CreateInstance(type, builder.Options, serviceProvider);

        return storage;
    }
    private static IConfigurationRoot BuildConfiguration()
    {
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: false);

        return builder.Build();
    }

    protected virtual void ConfigureServices(IServiceCollection services)
    {

    }
}
